package collection;


import java.util.HashSet;
import java.util.Objects;

/**
 * 集合练习
 */
public class Exercise06 {

    public static void main(String[] args) {

        /*
            以下代码输出什么
            已知：Persons类按照 id 和 name 重写了 hashCode 和 equals 方法，下面代码输出什么
         */
        HashSet hashSet = new HashSet();//ok
        Persons p1 = new Persons(1001, "AA");//ok
        Persons p2 = new Persons(1002, "BB");//ok
        hashSet.add(p1);//ok
        hashSet.add(p2);//ok
        p1.name = "CC";
        hashSet.remove(p1);//因为删除时底层会根据hash找索引，但是由于修改了name，现在计算p1的hash值和开始添加时不一样，所以索引值也改了，原先的p1也就无法锁定位置，所以删除失败
        System.out.println(hashSet);// p1 和 p2
        hashSet.add(new Persons(1001, "CC"));//ok 因为是由1001和cc计算的hash值，虽然和p1属性相同，但hashset添加元素后在链表的位置是不变的，所以p1还在原来的位置(1001和AA计算的hash决定的索引)，所以可以添加
        System.out.println(hashSet);//p1 和 p2 和 p3
        hashSet.add(new Persons(1001, "AA"));//ok 由于p1也是1001和AA 决定的索引值，所以这两者索引相同。而p1后来修改了属性cc，equals()方法判断和p1不相等。就挂载到p1后，形成链表
        System.out.println(hashSet);
    }
}

class Persons {

    public int id;

    public String name;

    public Persons(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null || getClass() != o.getClass()) return false;
        Persons persons = (Persons) o;
        return id == persons.id && Objects.equals(name, persons.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }

    @Override
    public String toString() {
        return "Persons{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}